package com.huoshan.im.server.listener;

import com.huoshan.im.server.ContextNaming;
import com.huoshan.im.server.SessionHolder;
import com.huoshan.im.server.dto.UserDto;
import com.huoshan.im.server.messaging.MessageId;
import com.huoshan.im.server.service.MessageSenderService;
import com.huoshan.im.server.service.UserService;
import com.qy.esports.common.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import online.chazi.netkit.Session;
import online.chazi.netkit.listener.NetkitSessionListener;
import online.chazi.netkit.messaging.Message;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 说明：作者很懒，什么都没留下
 * Created by 火山九日 on 2020-04-26 09:25
 */
@Slf4j
@Component
public class SessionListener implements NetkitSessionListener {

    @Resource
    private UserService userService;
    @Resource
    private MessageSenderService messageSenderService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public void onCreated(Session session) {
        log.debug("来啦~老弟~~{} @{}", session.getChannel().id(), session.getRemoteAddress());

        //建立会话，登录入redis
        userService.cacheUserRegisterServer(session.getChannel().id());
        //登录成功后，也需要入redis，转到登录成功：---> LoginAction

        //维护在线人数
        redisTemplate.opsForValue().increment("im-online-count");

        // 初始化Session发生错误的次数
        session.setAttribute(ContextNaming.CHANNEL_EXCEPTION_CAUGHT_COUNT, new AtomicInteger(0));

        // 存用户来源IP 与 PORT
        try {
            InetSocketAddress remoteAddress = (InetSocketAddress) session.getRemoteAddress();
            session.setAttribute(ContextNaming.SESSION_IP, remoteAddress.getHostString());
            session.setAttribute(ContextNaming.SESSION_PORT, remoteAddress.getPort());
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    public void onClosed(Session session) {
        log.debug("老弟慢走~~~{}", session.getChannel().id());

        //维护在线人数
        redisTemplate.opsForValue().decrement("im-online-count");

        // repeater连接断开后释放server与repeater绑定关系
        String repeaterId = (String) session.getAttribute(ContextNaming.SESSION_REPEATER_ID);
        if (!ObjectUtils.isEmpty(repeaterId)) {
            SessionHolder.removeRepeaterSession(repeaterId);
            return;
        }

        Long userId = (Long) session.getAttribute(ContextNaming.SESSION_USER_ID);

        if (userId == null) {
            log.warn("长连接上下文没有用户ID");
            return;
        }

        UserDto userDto = new UserDto();

        userDto.setUserId(userId);
        userDto.setClientType((String) session.getAttribute(ContextNaming.SESSION_CLIENT_TYPE));

        log.info("用户[userDto={}]，离开了，channel.id={}", userDto.toString(), session.getChannel().id());

        final Session userSession = SessionHolder.getUserSession(userDto);

        if (userSession == null) {
            log.warn("SessionGroup中，没有用户的长连接，userDto={}", userDto.toString());
            return;
        }

        final String oldChannelLongText = userSession.getChannel().id().asLongText();
        final String channelLongText = session.getChannel().id().asLongText();
        log.debug("oldChannelLongText=={},channelLongText={}", oldChannelLongText, channelLongText);

        //1为超时下线，0为挤下线
        int offlineType = 1;
        if (Objects.equals(oldChannelLongText, channelLongText)) {
            //超时下线
            log.info("超时下线， 用户ID:{}, 用户channel为：{}", userId, channelLongText);

            SessionHolder.removeUserSession(userDto);
            userService.removeCacheUserLoginServer(userDto, session.getChannel().id());

        } else {

            offlineType = 0;
            log.info("被挤下线， 用户ID:{}, 用户channel为：{}", userId, channelLongText);
        }

        removeUser(userId, offlineType);
    }

    private void removeUser(Long userId, int offlineType) {
        log.info("与客户端断开连接后发给repeater的消息: userId:{}", userId);

        HashMap<String, Object> hashMap = new HashMap<String, Object>(2);
        hashMap.put("fromUserId", userId);
        hashMap.put("offlineType", offlineType);

        // 构造中转消息
        Message message = new Message(MessageId.SERVER_ON_CLOSE_SESSION.id, JsonUtils.toJson(hashMap));
        log.info("下线透传消息給repeater：{}", JsonUtils.toJson(hashMap));
        // 转发消息
        messageSenderService.sendToRepeater(message);
    }
}
